﻿using System.Security.Cryptography;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using star_questionnair.Models;
using star_questionnair.Utilities;
using star_questionnairquestionnair.Services;

namespace star_questionnair.Services.impl;

public class UserService : IUserService
    {
        private readonly ApplicationDbContext _context;
        private readonly IMemoryCache _memoryCache;
        
        public UserService(ApplicationDbContext context, IMemoryCache memoryCache)
        {
            _context = context;
            _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); // 确保 _memoryCache 被正确注入
        }

        public async Task<User> GetByIdAsync(int id)
        {
            return await _context.Users.FindAsync(id);
        }

        public async Task<User> GetByUserNameAsync(string userName)
        {
            return await _context.Users.FirstOrDefaultAsync(u => u.UserName == userName);
        }

        public async Task<List<User>> GetAllAsync()
        {
            return await _context.Users.ToListAsync();
        }

        public async Task AddUserAsync(User user)
        {
            user.RegisteredTime = DateTime.UtcNow;
            user.Password = HashPassword(user.Password);
            await _context.Users.AddAsync(user);
            await _context.SaveChangesAsync();
        }

        public async Task UpdateUserAsync(User user)
        {
            var existingUser = await GetByIdAsync(user.Id);
            if (existingUser == null)
                throw new Exception("User not found");

            if (user.Password != null)
            {
                user.Password = HashPassword(user.Password);
            }
            foreach (var property in typeof(User).GetProperties())
            {
                var newValue = property.GetValue(user);
                if (newValue != null) // 只更新非 null 值
                {
                    property.SetValue(existingUser, newValue);
                }
            }

            // 更新更新时间字段
            existingUser.UpdatedTime = DateTime.Now;

            _context.Users.Update(existingUser);
            await _context.SaveChangesAsync();
        }

        public async Task DeleteUserAsync(int id)
        {
            var user = await GetByIdAsync(id);
            if (user != null)
            {
                _context.Users.Remove(user);
                await _context.SaveChangesAsync();
            }
        }

        public async Task<string> PasswordSignInAsync(string username, string password)
        {
            var user = await _context.Users.FirstOrDefaultAsync(u => u.UserName == username);
            
            if (user == null)
            {
                return "未知账户";  // Unknown account
            }
            
            var hashedPassword = HashPassword(password);

            bool success = user.Password == hashedPassword;


            return success ? "登陆成功" : "用户名或密码错误";
        }



        public enum ResetPasswordResult
        {
            Success,
            InvalidCode,
            UserNotFound
        }

        public async Task<ResetPasswordResult> ResetPasswordAsync(int userId, string newPassword, string code)
        {
            var user = await GetByIdAsync(userId);
            if (user == null)
            {
                return ResetPasswordResult.UserNotFound;
            }

            bool valid = await VerifyCodeAsync(userId, code);
            if (!valid)
            {
                return ResetPasswordResult.InvalidCode;
            }

            user.Password = HashPassword(newPassword);
            user.UpdatedTime = DateTime.UtcNow;
            _context.Users.Update(user);
            await _context.SaveChangesAsync();

            return ResetPasswordResult.Success;
        }


        public async Task SaveVerificationCodeAsync(int userId, string code)
        {
            // 保存验证码到内存缓存中
            _memoryCache.Set(userId, code, TimeSpan.FromMinutes(5)); // 设置缓存过期时间为5分钟
            var cachedCode = _memoryCache.TryGetValue(userId, out var storedCode) ? storedCode : null;
            Console.WriteLine($"验证码存储成功: {userId} -> {cachedCode}");
        }

        public async Task<bool> VerifyCodeAsync(int userId, string code)
        {
            // 从内存缓存中获取验证码
            bool exists = _memoryCache.TryGetValue(userId, out var storedCode);
    
            // 打印缓存值（调试用）
            Console.WriteLine($"验证码验证: {userId} -> 存储的验证码: {storedCode} vs 提供的验证码: {code}");

            return exists && string.Equals(code, storedCode);
        }

        public async Task<List<User>> GetUsersByAgeRangeAsync(int minAge, int maxAge)
        {
            var now = DateTime.UtcNow;
            var minDate = now.AddYears(-maxAge - 1).AddDays(1);
            var maxDate = now.AddYears(-minAge);

            return await _context.Users
                .Where(u => u.Birthday >= minDate && u.Birthday <= maxDate)
                .ToListAsync();
        }

        private string HashPassword(string password)
        {
            using var sha256 = SHA256.Create();
            var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
            return Convert.ToHexString(bytes);
        }
        
        public async Task<int> CalculateUserAgeAsync(int userId)
        {
            var user = await GetByIdAsync(userId);
            if (user == null || user.Birthday == null)
            {
                throw new ArgumentException("用户不存在或生日未设置");
            }

            DateTime birthDate = user.Birthday.Value;
            DateTime currentDate = DateTime.Now;

            if (birthDate > currentDate)
            {
                throw new ArgumentException("生日不能是未来的日期");
            }

            int age = currentDate.Year - birthDate.Year;
            if (birthDate.Date > currentDate.AddYears(-age)) age--;

            return age;
        }
        // 检查用户名是否已经存在
        public async Task<bool> IsUsernameExistAsync(string userName)
        {
            return await _context.Users.AnyAsync(u => u.UserName == userName);
        }

        public async Task<User> GetUserByIdAsync(int userId)
        {
            return await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
        }
    }